package com.gmrz.uap.user;

import com.gmrz.uap.cache.CacheStoreService;
import com.gmrz.uap.cfg.SystemConst;
import com.gmrz.uap.common.AuthInterceptor;
import com.gmrz.uap.common.ControllerSupport;
import com.gmrz.uap.common.UAPSSOHelper;
import com.gmrz.uap.model.Role;
import com.gmrz.uap.model.Tenant;
import com.gmrz.uap.model.User;
import com.gmrz.uap.model.UserRole;
import com.gmrz.uap.operlog.OperLogService;
import com.gmrz.uap.resource.ResourceInterceptor;
import com.gmrz.uap.role.RoleService;
import com.gmrz.uap.tenant.TenantService;
import com.gmrz.uap.util.Encodes;
import com.gmrz.uap.util.Strings;
import com.jfinal.aop.Before;
import com.jfinal.aop.Clear;
import com.jfinal.kit.PropKit;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Page;
import com.jfinal.plugin.activerecord.tx.Tx;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;

public class UserController extends ControllerSupport {

    private static final Logger LOG = LoggerFactory.getLogger(UserController.class);
    private static final UserService userService = UserService.me;

    /**
     * 管理员管理主页面
     */
    @Before(ResourceInterceptor.class)
    public void index() {
    }

    /**
     * 根据前台发过来的参数进行查询，可以进行分页，排序
     */
    public void list() {

        int page = getParaToInt(SystemConst.DATATABLE_PAGINATE_OFFSET, SystemConst.DATATABLE_PAGINATE_OFFSET_DEFAULT);
        int rows = getParaToInt(SystemConst.DATATABLE_PAGINATE_LIMIT, SystemConst.DATATABLE_PAGINATE_LIMIT_DEFAULT);

        String sort = getPara(SystemConst.DATATABLE_PAGINATE_SORT, SystemConst.DEFAULT_ORDERBY_CREATETS);
        String order = getPara(SystemConst.DATATABLE_PAGINATE_ORDER, SystemConst.DATATABLE_PAGINATE_ORDER_DEFAULT);

        try {
            User user = getModel(User.class);

            List<User> userList = UserService.me.findListForPaginate(user, page, rows, sort, order);
            List<User> conformRoleUserList = new ArrayList<>();

            if (!userList.isEmpty()) {
                User cacheUser = UAPSSOHelper.getUserByUapSessionId(getRequest());
                // 当前登录用户的角色
                List<Role> cacheUserRoles = RoleService.me.getRoleListByUserId(cacheUser.getUserId());
                boolean isSuper = isSuperAdmin(cacheUserRoles);

                for (int i = 0; i < userList.size(); i++) {
                    User userTemp = userList.get(i);
                    // 查询的数据库中用户的角色
                    List<Role> roles = RoleService.me.getRoleListByUserId(userTemp.getUserId());
                    // 判断当前登录用户的角色是否拥有此用户的操作权限
                    if (isSuper || conformUserRole(cacheUserRoles, roles)){
                        String roleNameArr = "";
                        if (!roles.isEmpty()) {
                            for (Role role : roles) {
                                roleNameArr += role.getRoleName() + "/";
                            }

                            roleNameArr = roleNameArr.substring(0, roleNameArr.lastIndexOf("/"));
                        }

                        if (StrKit.notBlank(roleNameArr)) {
                            userTemp.put("roleNames", roleNameArr);
                        }
                        conformRoleUserList.add(userTemp);
                    }
                }
            }

            Page<User> descPage = null;
            // 总记录数
            int totalRow = conformRoleUserList.size();

            if (totalRow == 0) {
                // 如果没有记录则返回空页
                descPage = new Page<User>(new ArrayList<User>(0), page, rows, 0, 0);
            }else {
                // 总页数
                int totalPage = totalRow / rows;
                if (totalRow % rows != 0) {
                    totalPage++;
                }
                List<User> users = new ArrayList<>();
                if ((page * rows) > totalRow){
                    for (int i = ((page-1) * rows); i < totalRow; i++){
                        users.add(conformRoleUserList.get(i));
                    }
                }else {
                    for (int i = ((page-1) * rows); i < (page * rows); i++){
                        users.add(conformRoleUserList.get(i));
                    }
                }
                descPage = new Page<User>(users, page, rows, totalPage, totalRow);
            }

            result.put(SystemConst.DATATABLE_PAGINATE_TOTAL, descPage.getTotalRow());
            result.put(SystemConst.DATATABLE_PAGINATE_ROWS, descPage.getList());
        } catch (Exception e) {
            LOG.error("搜索关键字格式错误", e);
            result.put(SystemConst.DATATABLE_PAGINATE_TOTAL, 0);
            result.put(SystemConst.DATATABLE_PAGINATE_ROWS, new ArrayList<User>());
        }

        render(responseJsonRender(result));
    }


    /**
     *  当前用户是否为超级管理员
     * @param cacheUserRoles
     * @return
     */
    public boolean isSuperAdmin(List<Role> cacheUserRoles){
        if (cacheUserRoles == null || cacheUserRoles.size() == 0){
            return false;
        }
        for (Role role : cacheUserRoles){
            if (StringUtils.isNotBlank(role.getPid()) && Integer.valueOf(role.getPid()) == 0 ){
                return true;
            }
        }
        return false;
    }



    /**
     *  当前登录用户的角色权限可以查看的 用户数据
     * @param cacheUserRole 当前用户的角色
     * @param tempUserRole  数据库查询出的用户的角色
     * @return
     */
    public boolean conformUserRole(List<Role> cacheUserRole, List<Role> tempUserRole){
        if (cacheUserRole == null || cacheUserRole.size() == 0){
            return false;
        }
        if (tempUserRole == null || tempUserRole.size() == 0){
            return false;
        }
        // 角色权限级别默认设置2，权限级别从0 ~ 2 递减，2 权限级别最低
        int cacheUserRoleLevel = 2;
        for (Role role : cacheUserRole){
            String pid = role.getPid()== null ? "2" : role.getPid();
            if (Integer.valueOf(pid) < cacheUserRoleLevel ){
                cacheUserRoleLevel = Integer.valueOf(role.getPid());
            }
        }

        int tempUserRoleLevel = 2;
        for (Role role : tempUserRole){
            String pid = role.getPid()== null ? "2" : role.getPid();
            if (Integer.valueOf(pid) < tempUserRoleLevel ){
                tempUserRoleLevel = Integer.valueOf(role.getPid());
            }
        }

        if (cacheUserRoleLevel <= tempUserRoleLevel){
            return true;
        }

        return false;
    }




    /**
     * 增加页面跳转
     */

    public void add() {
        setAttr("roles", getConformUserRole(RoleService.me.findAll()));
        List<Tenant> tenantList = TenantService.me.getAllTenants();
        setAttr("tenantList", tenantList);
        render("form" + SystemConst.VIEW_EXTENDSION);
    }


    /**
     *  当前用户所属角色可以操作的角色
     * @param allRole  全部角色
     * @return
     */
    public List<Role> getConformUserRole(List<Role> allRole){
        User cacheUser = UAPSSOHelper.getUserByUapSessionId(getRequest());
        // 当前登录用户的角色
        List<Role> cacheUserRoles = RoleService.me.getRoleListByUserId(cacheUser.getUserId());
        int cacheUserRoleLevel = 2;
        for (Role role : cacheUserRoles){
            String pid = role.getPid()== null ? "2" : role.getPid();
            if (Integer.valueOf(pid) < cacheUserRoleLevel ){
                cacheUserRoleLevel = Integer.valueOf(role.getPid());
            }
        }

        List<Role> conformUserRoles = new ArrayList<>();
        if (allRole !=null && allRole.size() > 0){
            for (Role role : allRole){
                int tempRoleLevel = role.getPid()==null ? 2 : Integer.valueOf(role.getPid());
                if (cacheUserRoleLevel <= tempRoleLevel){
                    conformUserRoles.add(role);
                }
            }
        }
        return conformUserRoles;
    }



    /**
     * 保存数据信息
     */
    @Before(Tx.class)
    public void save() {

        User user = getModel(User.class);
        String[] roleIds = getParaValues("role");
        if (user.getDes() == null) {
            user.setDes("");
        }
        user.setPwd(Encodes.oprSha256Instance(user.getPwd()));

        if (null == user) {
            message = getRes().get("system.validator.paramnull");
            return;
        }

        boolean exist = UserService.me.exist(user.getUserName());

        if (exist) {

            flag = UserService.me.save(user);

            if (flag) {

                UserService.me.removeByUserId(user.getUserId());//删除用户关联的角色
                UserRole userRole = new UserRole();
                userRole.setUserId(user.getUserId());
                flag = UserService.me.userRoleSave(userRole, roleIds);
                if (flag) {
                    message = getRes().get("system.validator.add.success");
                } else {
                    message = getRes().get("user.validator.userrole.error");
                }

            } else {
                message = getRes().get("system.validator.add.error");
            }

        } else {
            message = getRes().get("user.form.exist");
        }

        //增加系统操作日志
        OperLogService.me.addOperLog(getRes().get("resource.form.adduser"), user.getUserName(), flag, message, getRequest());

        result.put(SystemConst.RESPONSE_RESULT_FLAG, flag);
        result.put(SystemConst.RESPONSE_RESULT_MESSAGE, message);
        render(responseJsonRender(result));
    }

    /**
     * 编辑页面跳转
     */
    public void edit() {
        User user = UserService.me.findOne(getPara());
        setAttr("user", user);

        setAttr("roles", getConformUserRole(RoleService.me.findByUserId(user.getUserId())));

        List<Tenant> tenantList = TenantService.me.getAllTenants();
        setAttr("tenantList", tenantList);

        render("form" + SystemConst.VIEW_EXTENDSION);
    }

    /**
     * 修改数据信息
     */
    @Before(Tx.class)
    public void update() {
        User user = getModel(User.class);
        if (user.getDes() == null) {
            user.setDes("");
        }

        // 判断“备注”填写的长度超过了页面中文本框限定的300
        if (user.getDes().length() > 512) {
            result.put(SystemConst.RESPONSE_RESULT_FLAG, flag);
            result.put(SystemConst.RESPONSE_RESULT_MESSAGE, "可能由于存在sql或表单注入，系统对文本进行处理后的长度超过了限定长度！");
            render(responseJsonRender(result));
            return;
        }

        String[] roleIds = getParaValues("role");

        if (null == user) {
            message = getRes().get("system.validator.paramnull");
            return;
        }

        flag = UserService.me.update(user);

        if (flag) {
            UserService.me.removeByUserId(user.getUserId());//删除用户关联的角色
            UserRole userRole = new UserRole();
            userRole.setUserId(user.getUserId());
            flag = UserService.me.userRoleSave(userRole, roleIds);
            if (flag) {
                // 从缓存中取出"当前"用户信息
                User cacheUser = UAPSSOHelper.getUserByUapSessionId(getRequest());
                if (cacheUser != null && cacheUser.getUserName().equals(user.getUserName())){
                    // 更新保存到缓存中"当前"用户信息
                    UAPSSOHelper.setUserIntoCache(getRequest(), user, UAPSSOHelper.UAP_SESSION_EXPIRE);
                }
                message = getRes().get("system.validator.edit.success");
            } else {
                message = getRes().get("user.validator.userrole.error");
            }
        } else {
            message = getRes().get("system.validator.edit.error");
        }

        //增加系统操作日志
        OperLogService.me.addOperLog(getRes().get("resource.form.edituser"), user.getUserName(), flag, message, getRequest());

        result.put(SystemConst.RESPONSE_RESULT_FLAG, flag);
        result.put(SystemConst.RESPONSE_RESULT_MESSAGE, message);

        render(responseJsonRender(result));
    }

    /**
     * 根据ID删除数据信息，可以同时删除多个，数据使用逗号(,)隔开
     */
    public void remove() {

        String ids = getPara(0);
        String names = getPara(1);

        if (StrKit.isBlank(ids)) {
            message = getRes().get("system.validator.paramnull");
            result.put(SystemConst.RESPONSE_RESULT_FLAG, flag);
            result.put(SystemConst.RESPONSE_RESULT_MESSAGE, message);
            render(responseJsonRender(result));
            return;
        }

        User user = UAPSSOHelper.getUserByUapSessionId(getRequest());

        for (String userName : names.split(SystemConst._DEFAULT_SEPARATOR_COMMA)) {
            if (StrKit.equals(userName, user.getUserName())) {
                result.put(SystemConst.RESPONSE_RESULT_FLAG, flag);
                result.put(SystemConst.RESPONSE_RESULT_MESSAGE, "不能删除当前登录用户，请重新选择！");
                render(responseJsonRender(result));
                return;
            }
        }


        flag = UserService.me.remove(ids);

        if (flag) {
            message = getRes().get("system.validator.remove.success");
        } else {
            message = getRes().get("system.validator.remove.error");
        }

        //增加系统操作日志
        OperLogService.me.addOperLog(getRes().get("resource.form.removeuser"), names, flag, message, getRequest());

        result.put(SystemConst.RESPONSE_RESULT_FLAG, flag);
        result.put(SystemConst.RESPONSE_RESULT_MESSAGE, message);
        render(responseJsonRender(result));
    }

    @Clear(AuthInterceptor.class)
    public void login() {
        int maxAgeInSeconds = 30 * 24 * 60 * 60; //COOKIE过期时间

        //如果COOKIE中没有国际化名称，将设置成操作系统相关的语言
        String locale = SystemConst.SYSTEM_DEFAULT_LOCALE;
        setCookie(SystemConst.COOKIE_I18N, locale/*getCookie(SystemConst.COOKIE_I18N, locale)*/, maxAgeInSeconds);

        //如果COOKIE中没有租户ID，将默认的租户ID放到COOKIE中
        String tenantId = getCookie(SystemConst.COOKIE_TENANT_ID);
        if (StringUtils.isNotBlank(tenantId)) {
            Tenant tenant = TenantService.me.getByTenantId(tenantId);
            if (null == tenant) {
                tenantId = TenantService.me.getFirstTenant().getTenantId();
            }
        } else {
            tenantId = TenantService.me.getFirstTenant().getTenantId();
        }
        setCookie(SystemConst.COOKIE_TENANT_ID, tenantId, maxAgeInSeconds);

    }


    /**
     * 管理员登录验证
     */
    @Clear(AuthInterceptor.class)
    @Before(LoginValidator.class)
    public void doLogin() {
        User user = getModel(User.class);

        CacheStoreService cacheStoreService = UAPSSOHelper.getCacheStoreServiceForSession();

        //登录失败缓存键
        String userLoginWrongCountKey = user.getUserName() + "-" + UAPSSOHelper.LOGIN_WRONG_COUNT;
        String currentLoginWrongCountValue = cacheStoreService.getStr(userLoginWrongCountKey);//从缓存中获取登录失败次数
        Integer currentLoginWrongCount = 0;

        if (StringUtils.isBlank(currentLoginWrongCountValue)) {//如果缓存中的为空，则设置为0
            cacheStoreService.set(userLoginWrongCountKey, String.valueOf(currentLoginWrongCount), UAPSSOHelper.UAP_SESSION_EXPIRE);//登录失败计数
        } else {
            currentLoginWrongCount = Integer.parseInt(currentLoginWrongCountValue);
        }

        //系统默认登录失败限制次数
        int loginWrongCount = PropKit.use(SystemConst.SYSTEM_CONFIG_FILE).getInt("login.wrong.count");

        //如果登录失败次数已经超过限制则返回登录页面
        if (currentLoginWrongCount < loginWrongCount) flag = true;
        if (!flag) {

            Long remainTime = cacheStoreService.remainingTime(userLoginWrongCountKey) != null ? cacheStoreService.remainingTime(userLoginWrongCountKey) / 1000 : UAPSSOHelper.UAP_SESSION_EXPIRE;
            LOG.info("登录错误次数在缓存中剩余时间 ==> " + remainTime);
            setAttr(SystemConst.RESPONSE_RESULT_MESSAGE, "登录错误已经超过上限" + loginWrongCount + "次,请" + remainTime / 60 + "分钟后再进行登录!");
            forwardAction("/user/login");
            return;
        }


        //验证码校验
        flag = validateCaptcha("imgcode");
        if (!flag) {
            setAttr(SystemConst.RESPONSE_RESULT_MESSAGE, "验证码错误");
            forwardAction("/user/login");
            return;
        }


        flag = UserService.me.exist(user.getUserName());
        if (flag) {

            cacheStoreService.set(userLoginWrongCountKey, String.valueOf(++currentLoginWrongCount), UAPSSOHelper.UAP_SESSION_EXPIRE);//登录失败计数

            LOG.info(getRes().get("user.validator.up.wrong"));
            setAttr(SystemConst.RESPONSE_RESULT_MESSAGE, getRes().get("user.validator.up.wrong"));
            forwardAction("/user/login");
            return;
        }

        user.setPwd(Encodes.oprSha256Instance(user.getPwd()));

        user = UserService.me.findUserByUsernameAndPassword(user.getUserName(), user.getPwd());

        if (null != user) {

            //检查密码是否过期
            boolean passwordExpire = UserService.me.passwordExpire(user.getUserName());
            if (passwordExpire) {
                setAttr("errorMsg", "登录密码已经过期，请修改密码后再进行登录!");
                setAttr("user", user);
                render("passwordExpire" + SystemConst.VIEW_EXTENDSION);
                return;
            }

            //将登录过后的用户信息保存到缓存中
            UAPSSOHelper.setUserIntoCache(getRequest(), user, UAPSSOHelper.UAP_SESSION_EXPIRE);

            //增加系统操作日志
            OperLogService.me.addOperLog(getRes().get("user.login.submit"), user.getUserName(), true, message, getRequest());

            redirect("/");
        } else {
            cacheStoreService.set(userLoginWrongCountKey, String.valueOf(++currentLoginWrongCount), UAPSSOHelper.UAP_SESSION_EXPIRE);//登录失败计数

            setAttr(SystemConst.RESPONSE_RESULT_MESSAGE, "用户名或者密码错误第" + currentLoginWrongCount + "次,上限" + loginWrongCount + "次,超过上限后会锁定30分钟");
            forwardAction("/user/login");
        }

    }

    @Clear(AuthInterceptor.class)
    public void doPasswordExpire() {

    }


    /**
     * 注销管理员
     */
    @Clear
    public void exit() {

        //增加系统操作日志
        OperLogService.me.addOperLog(getRes().get("system.common.logout"), true, message, getRequest());

        //从缓存中移除用户信息
        UAPSSOHelper.removeUserFromCache(getRequest());

        //getSession().removeAttribute(SystemConst.SESSION_USER);
        //getSession().removeAttribute(SystemConst.RESPONSE_RESOURCE_MESSAGE);

        redirect("/");
    }

    /**
     * 判断管理员是否存在
     */
    public void exist() {
        flag = UserService.me.exist(getPara("user.username"));
        render(responseJsonRender(flag));
    }

    /**
     * 分配权限
     */
    public void privileges() {
        List<Role> roles = RoleService.me.findByUserId(getPara());
        setAttr("roles", getConformUserRole(roles));
        setAttr("userId", getPara());
    }

    /**
     * 用户角色关联成功
     */
    public void userRoleSave() {
        UserRole userRole = getModel(UserRole.class);
        if (StrKit.isBlank(getPara("role"))) {
            result.put(SystemConst.RESPONSE_RESULT_FLAG, flag);
            result.put(SystemConst.RESPONSE_RESULT_MESSAGE, "请选择角色");
            render(responseJsonRender(result));
            return;
        }
        String[] roleIds = getParaValues("role");

        UserService.me.removeByUserId(userRole.getUserId());//删除用户关联的角色

        flag = UserService.me.userRoleSave(userRole, roleIds);

        if (flag) {
            message = getRes().get("user.validator.userrole.success");
        } else {
            message = getRes().get("user.validator.userrole.error");
        }

        String roles = "";

        if (roleIds.length >= 1) {
            for (String role_id : roleIds) {
                Role r = RoleService.me.findOne(role_id);
                roles += r.getRoleName() + ",";
            }
        }

        //增加系统操作日志
        OperLogService.me.addOperLog2(getRes().get("resource.form.privileges"), User.dao.findById(userRole.getUserId()).getUserName(), roles, flag, message, getRequest());

        result.put(SystemConst.RESPONSE_RESULT_FLAG, flag);
        result.put(SystemConst.RESPONSE_RESULT_MESSAGE, message);
        render(responseJsonRender(result));
    }

    public void resetPwd() {


        //setAttr("user", (User) getSession().getAttribute(SystemConst.SESSION_USER));

        setAttr("user", UAPSSOHelper.getUserByUapSessionId(getRequest()));
    }

    /**
     * 修改密码
     */
    @Clear(AuthInterceptor.class)
    public void updatePwd() {
        // 获取到页面中输入的原密码
        String oldPwd = getPara("oldPwd");
        // 获取到页面中输入的新密码
        String newPwd = getPara("newPwd");

        //User user = (User) getSession().getAttribute(SystemConst.SESSION_USER);
        // 从缓存中取出用户信息
        User user = UAPSSOHelper.getUserByUapSessionId(getRequest());
        if (null == user) {
            user = getModel(User.class);
        }
        // 对明文的页面输入的旧密码进行SHA256加密
        String oldPwdHash = Encodes.oprSha256Instance(oldPwd);
        // 根据用户id去用户表中查询用户数据
        User userTmp = userService.findOne(user.getUserId());

        if (StringUtils.equals(oldPwdHash, userTmp.getPwd())) {
            // 进行用户密码的更新
            flag = userService.updatePassword(Encodes.oprSha256Instance(newPwd), user.getUserId());
            if (flag) {
                message = getRes().get("user.form.update.success");
            } else {
                message = getRes().get("user.form.update.failure");
            }
        } else {
            flag = false;
            message = getRes().get("user.form.oldpwd.error");
        }

        // 增加系统操作日志
        OperLogService.me.addOperLog(getRes().get("resource.form.user.resetpwd"), user.getUserName(), flag, message, getRequest());

        result.put(SystemConst.RESPONSE_RESULT_FLAG, flag);
        result.put(SystemConst.RESPONSE_RESULT_MESSAGE, message);

        render(responseJsonRender(result));
    }


    public void resetpwd() {

        String ids = getPara();

        if (StrKit.isBlank(ids)) {
            message = getRes().get("system.validator.paramnull");
            return;
        }

        flag = UserService.me.resetPwds(ids);

        if (flag) {
            message = getRes().get("user.pwd.reset.success");
        } else {
            message = getRes().get("user.pwd.reset.error");
        }

        //增加系统操作日志
        OperLogService.me.addOperLog(getRes().get("resource.form.user.resetpwd"), ids, flag, message, getRequest());

        result.put(SystemConst.RESPONSE_RESULT_FLAG, flag);
        result.put(SystemConst.RESPONSE_RESULT_MESSAGE, message);
        render(responseJsonRender(result));
    }

}
